<?php
/**
 * Created by PhpStorm.
 * User: ownfi
 * Date: 2017-04-03
 * Time: 1:04
 */

namespace App\Services\Impl;


use App\Common\Constant\Params;
use App\Models\CouponGrantList;
use App\Models\Goods;
use App\Models\HistoryMerchantBalance;
use App\Models\Merchant;
use App\Models\MerchantTradeLog;
use App\Models\PricedApply;
use App\Services\IMerchantService;
use DB;
use Illuminate\Support\Collection;
use Log;

class MerchantServiceImpl implements IMerchantService
{
    public function all(array $wheres = [])
    {
        $model = Merchant::alias('t1')->select('t1.*')->orderBy('t1.me_add_time','DESC');
        if ($wheres){
            foreach ($wheres as $where){
                if ($where[0] == 'me_username'){
                    $model->where([$where])->orWhere('t1.me_truename',$where[1],$where[2]);
                }else{
                    $model->where('t1.'.$where[0],$where[1],$where[2]);
                }
            }
        }
        return $model->paginate(config('common.perpage'));
    }

    public function genBalanceHistory($trade_id)
    {
        $history = HistoryMerchantBalance::where('trade_id',$trade_id)->first();
        if ($history){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'trade history already exists'));
            return true;
        }
        $trade_log = MerchantTradeLog::find($trade_id);
        if(!$trade_log){
            throw new \Exception('miss trade log');
        }

        $new_balance = $trade_log->balance;
        $current_balance = ($trade_log->direction == Params::TRADE_DIRECTION_OUT)
            ? $new_balance + $trade_log->amount
            : $new_balance - $trade_log->amount;

        return HistoryMerchantBalance::create([
            'trade_id'=>$trade_id,
            'merchant_id'=>$trade_log->merchant_id,
            'direction'=>$trade_log->direction,
            'amount'=>$trade_log->amount,
            'current_balance'=>$current_balance,
            'new_balance'=>$new_balance,
        ]);
    }

    public function subtractBalance($trade_id, $merchant_id, $amount)
    {
        $history = HistoryMerchantBalance::where('trade_id',$trade_id)->where('merchant_id',$merchant_id)->first();
        if ($history && ($history->direction == Params::TRADE_DIRECTION_OUT)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'trade history already exists'));
            return true;
        }

        DB::beginTransaction();
        try{
            $amount = floatval($amount);

            $model = Merchant::lockForUpdate()->find($merchant_id);
            if (empty($model)){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss merchant'));
                DB::rollBack();
                return false;
            }
            if (empty($model->me_money) || ($model->me_money < $amount)){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'balance not enough'));
                DB::rollBack();
                return false;
            }
            $current_balance = $model->me_money;
            $new_balance = $current_balance - $amount;
            $model->me_money = DB::raw("me_money - {$amount}");

            $ret = HistoryMerchantBalance::create([
                    'trade_id'=>$trade_id,
                    'merchant_id'=>$merchant_id,
                    'direction'=>Params::TRADE_DIRECTION_OUT,
                    'amount'=>$amount,
                    'current_balance'=>$current_balance,
                    'new_balance'=>$new_balance,
                ]) && $model->save() && MerchantTradeLog::find($trade_id)->update(['status'=>Params::TRADE_STATUS_SUCCESS]);

            if ($ret){
                DB::commit();
            }else{
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'subtract fail'));
                DB::rollBack();
            }
            return $ret;
        }catch (\Exception $e){
            DB::rollBack();
            throw $e;
        }
    }

    public function raiseBalance($trade_id, $merchant_id, $amount)
    {
        $history = HistoryMerchantBalance::where('trade_id',$trade_id)->where('merchant_id',$merchant_id)->first();
        if ($history && ($history->direction == Params::TRADE_DIRECTION_IN)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'trade history already exists'));
            return true;
        }

        DB::beginTransaction();
        try{
            $amount = floatval($amount);

            $model = Merchant::lockForUpdate()->find($merchant_id);
            if (empty($model)){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss merchant'));
                DB::rollBack();
                return false;
            }
            $current_balance = $model->me_money;
            $new_balance = $current_balance + $amount;
            $model->me_money = DB::raw("me_money + {$amount}");

            $ret = HistoryMerchantBalance::create([
                    'trade_id'=>$trade_id,
                    'merchant_id'=>$merchant_id,
                    'direction'=>Params::TRADE_DIRECTION_IN,
                    'amount'=>$amount,
                    'current_balance'=>$current_balance,
                    'new_balance'=>$new_balance,
                ]) && $model->save() && MerchantTradeLog::find($trade_id)->update(['status'=>Params::TRADE_STATUS_SUCCESS]);

            if ($ret){
                DB::commit();
            }else{
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'raise fail'));
                DB::rollBack();
            }
            return $ret;
        }catch (\Exception $e){
            DB::rollBack();
            throw $e;
        }
    }

    public function disable($merchant_id)
    {
        return Merchant::find($merchant_id)->update(['me_status'=>Params::MERCHANT_STATUS_DISABLE]);
    }

    public function enable($merchant_id)
    {
        return Merchant::find($merchant_id)->update(['me_status'=>Params::MERCHANT_STATUS_NORMAL]);
    }

    public function couponList($merchant_id)
    {
        $model = CouponGrantList::where('cg_meid',$merchant_id)->orderBy('cg_add_time','DESC')->with(['merchant','coupon']);
        return $model->paginate(config('common.perpage'));
    }

    public function goodsList($merchant_id)
    {
        $model = Goods::where('go_me_id',$merchant_id)->orderBy('go_add_time','DESC')->with(['merchant']);
        return $model->paginate(config('common.perpage'));
    }

    public function applyPricedList()
    {
        $model = PricedApply::orderBy('add_time','DESC')->with(['merchant']);
        return $model->paginate(config('common.perpage'));
    }
}